package cn.iocoder.yudao.module.im.controller.app.member;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.module.im.controller.admin.member.vo.MemberConversationRespVO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.mp.api.user.MpUserApi;
import cn.iocoder.yudao.module.trade.api.config.TradeConfigApi;
import cn.iocoder.yudao.module.trade.api.config.dto.TradeConfigRespDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

import cn.iocoder.yudao.module.im.controller.app.member.vo.*;
import cn.iocoder.yudao.module.im.dal.dataobject.member.MemberConversationDO;
import cn.iocoder.yudao.module.im.service.member.MemberConversationService;

@Tag(name = "用户 APP - IM会话")
@RestController
@RequestMapping("/im/member-conversation")
@Validated
public class AppMemberConversationController {

    @Resource
    private MemberConversationService memberConversationService;

    @Resource
    private MemberUserApi memberUserApi;

    @Resource
    private TradeConfigApi tradeConfigApi;

    @Resource
    private MpUserApi mpUserApi;

    @PostMapping("/create")
    @Operation(summary = "创建IM会话")
    @PreAuthenticated
    public CommonResult<Long> createMemberConversation(@Valid @RequestBody AppMemberConversationSaveReqVO createReqVO) {
        MemberUserRespDTO member = memberUserApi.getUser(getLoginUserId());

        TradeConfigRespDTO config = tradeConfigApi.getTradeConfig();
        if(!config.getAuthEnabled()){
            if(StringUtils.isBlank(member.getPhoto())){
                throw exception(USER_PHOTO_EMPTY);
            }
        }

        if(!config.getAuthEnabled() && config.getQrcodeEnabled()){
            if(!mpUserApi.getQrcode(getLoginUserId())){
                throw exception(USER_FANS_QRCODE);
            }
        }

        if(CommonStatusEnum.isDisable(member.getStatus())){
            throw exception(AUTH_LOGIN_USER_DISABLED);
        }
        // 更新在线时间
        memberUserApi.updateUserLogin(getLoginUserId(), getClientIP());

        return success(memberConversationService.createMemberConversation(getLoginUserId(), createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新IM会话")
    public CommonResult<Boolean> updateMemberConversation(@Valid @RequestBody AppMemberConversationSaveReqVO updateReqVO) {
        memberConversationService.updateMemberConversation(updateReqVO);
        return success(true);
    }

    @PutMapping("/pinned")
    @Operation(summary = "置顶/取消置顶IM会话")
    @PreAuthenticated
    public CommonResult<Boolean> pinnedMemberConversation(@Valid @RequestBody AppMemberConversationSaveReqVO updateReqVO) {
        memberConversationService.pinnedMemberConversation(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除IM会话")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthenticated
    public CommonResult<Boolean> deleteMemberConversation(@RequestParam("id") Long id) {
        memberConversationService.deleteMemberConversation(id);
        return success(true);
    }

    @DeleteMapping("/slashed")
    @Operation(summary = "拉黑IM会话")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthenticated
    public CommonResult<Boolean> slashedMemberConversation(@RequestParam("id") Long id) {
        memberConversationService.slashedMemberConversation(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得IM会话")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<AppMemberConversationRespVO> getMemberConversation(@RequestParam("id") Long id) {
        MemberConversationDO memberConversation = memberConversationService.getMemberConversation(id);
        return success(BeanUtils.toBean(memberConversation, AppMemberConversationRespVO.class));
    }

    @GetMapping("/getRandom")
    @Operation(summary = "随机获得IM会话")
    @PreAuthenticated
    public CommonResult<MemberConversationRespVO> getRandom() {
        return success(memberConversationService.getRandomMemberConversation(getLoginUserId()));
    }

    @GetMapping("/page")
    @Operation(summary = "获得IM会话分页")
    @PreAuthenticated
    public CommonResult<PageResult<AppMemberConversationRespVO>> getMemberConversationPage(@Valid AppMemberConversationPageReqVO pageReqVO) {
        // 更新在线时间
        memberUserApi.updateUserLogin(getLoginUserId(), getClientIP());

        pageReqVO.setByUserId(getLoginUserId());
        PageResult<MemberConversationDO> pageResult = memberConversationService.getMemberConversationPage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(PageResult.empty());
        }
        // 拼接关联数据
        Map<Long, MemberUserRespDTO> memberUserMap = memberUserApi.getUserMap(convertList(pageResult.getList(), MemberConversationDO::getUserId));
        PageResult<AppMemberConversationRespVO> page = BeanUtils.toBean(pageResult, AppMemberConversationRespVO.class);
        for(AppMemberConversationRespVO conversation : page.getList()){
            MemberUserRespDTO member = memberUserMap.getOrDefault(conversation.getUserId(), new MemberUserRespDTO());
            conversation.setNickname(member.getNickname());
            conversation.setAvatar(member.getAvatar());
            conversation.setSex(member.getSex());
            // 计算是否在线
            DateTime endDate = DateUtil.date();
            DateTime beginDate = DateUtil.offsetMinute(DateUtil.date(), -5);
            conversation.setOnline(DateUtil.isIn(new DateTime(member.getUpdateTime()), beginDate, endDate));
        }

        return success(page);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出IM会话 Excel")
    @ApiAccessLog(operateType = EXPORT)
    public void exportMemberConversationExcel(@Valid AppMemberConversationPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<MemberConversationDO> list = memberConversationService.getMemberConversationPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "IM会话.xls", "数据", AppMemberConversationRespVO.class,
                        BeanUtils.toBean(list, AppMemberConversationRespVO.class));
    }

}